Viewport transform

The viewport transform maps everything in normalized device coordinates (the (-1,-1,-1),(1,1,1) cube at the origin) to a viewport of image pixels. The pixel dimensions change depending on image size; we will give them the designation \(n_x\) and \(n_y\). Most of our images have been displayed in \(512 \times 512\) windows, so \(n_x=512\) and \(n_y=512\) for most of our images.

It is just translation and scaling to map the NDC cube to the image. However, we want the pixel centers to align with integer values, so we will need to translate by an additional half a pixel (0.5). So the enclosing image region is: $$ [-\frac{1}{2},\frac{1}{2}], [n_x-\frac{1}{2},ny-\frac{1}{2}] $$ The viewport transform has a z component and it is the same as the z component in NDC. However, we will discuss its effect later.

The viewport transform is then: Translate NDC so bottom left corner is at origin... $$ \begin{bmatrix} 1 & 0 & 0 & 1 \\ 0 & 1 & 0 & 1 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} $$ ...then scale so the NDC region matches image pixel coordinates... $$ \begin{bmatrix} \frac{n_x}{2} & 0 & 0 & 0 \\ 0 & \frac{n_y}{2} & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} $$ ... then translate to account for pixel centers (half a pixel). $$ \begin{bmatrix} 1 & 0 & 0 & -\frac{1}{2} \\ 0 & 1 & 0 & -\frac{1}{2} \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} $$
Combine the all together for the complete viewport transform: $$ \begin{bmatrix} 1 & 0 & 0 & -\frac{1}{2} \\ 0 & 1 & 0 & -\frac{1}{2} \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} \frac{n_x}{2} & 0 & 0 & 0 \\ 0 & \frac{n_y}{2} & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 1 \\ 0 & 1 & 0 & 1 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} = \begin{bmatrix} \frac{n_x}{2} & 0 & 0 & \frac{n_x-1}{2} \\ 0 & \frac{n_y}{2} & 0 & \frac{n_y-1}{2} \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} $$